%{
	StringBuilder buffer = null;
	IExpressionFactory _ExpressionFactory = null;
	IStatementFactory _StatementFactory = null;

	public IStatement StartStatement = null;

	public ILogger Logger = DebugLogger.Instance;
%}

%namespace Infinity.Parser.Syntax

%using System.Linq

%using Infinity.Parser.Lexical
%using Infinity.Expressions
%using Infinity.Statements
%using Infinity.Expressions.Constant
%using Infinity.Statements.Block
%using Infinity.Statements.Condition
%using Infinity.Statements.Declare
%using Infinity.Statements.Program
%using Infinity.Common.Logger;
%using Infinity.Common;

%scanbasetype LexicalParser
%parsertype SyntaxParser
%partial

%start function
%visibility public
%tokentype Token

%token PROCEDURE
%token FUNCTION
%token OPERATOR

%token PREFIX
%token INFIX
%token POSTFIX
%token ITERATIVE

%token PRECEDENCE

%token DECLARE
%token SKIP
%token BEGIN
%token END
%token RETURN
%token IF
%token THEN
%token ELSE
%token ELSEIF
%token WHILE
%token LOOP
%token FOR
%token FOREACH
%token DO
%token IN
%token OUT
%token TO
%token BY
%token VAR
%token CONST
%token TYPE
%token WHERE

%token ASSIGNMENT
%token END_COMMAND
%token COMMA_SEPARATOR
%token COLON
%token LINEAR_COLON
%token DOTS
%token DOT

%token LEFT_REGULAR_PARENTHESES
%token RIGHT_REGULAR_PARENTHESES
%token LEFT_SQUARE_PARENTHESES
%token RIGHT_SQUARE_PARENTHESES
%token LEFT_CURLY_PARENTHESES
%token RIGHT_CURLY_PARENTHESES
%token LEFT_POINTY_PARENTHESES
%token RIGHT_POINTY_PARENTHESES

%token PRECONDITION
%token POSTCONDITION

%token OPERATOR_COMMAND
%token NUMERIC_OPERATOR
%token LOGICAL_OPERATOR

%token NUMBER
%token STRING
%token BOOLEAN

%token IDENTIFIER
%token SYMBOL

%type <_Expression> expression element precondition postcondition
%type <_ConstantExpression> constant set_constant
%type <_ConstantExpression> range_constant
%type <_ExpressionList> arguments_list expression_base
%type <_ConstraintStatement> constraints
%type <_Value> identifier_name symbol_name type_name
%type <_Statement> assignment while_statement foreach_statement for_statement if_statement block_statement
%type <_IfStatementList> else_if_statement
%type <_BlockStatement> command_statement
%type <_VariableStatement> declaration set_identifier
%type <_VariableStatementList> declarations_block declare_variable set_identifier_list
%type <_TypeDeclareStatement> type_parameter type_declaration

%union
{
	public IConstantExpression _ConstantExpression;
	public IExpression _Expression;
	public IStatement _Statement;
	public ITypeDeclareStatement _TypeDeclareStatement;

	public IBlockStatement _BlockStatement;
	public List<IIfStatement> _IfStatementList;
	public IConstraintStatement _ConstraintStatement;
	public IVariableStatement _VariableStatement;
	public IEnumerable<IVariableStatement> _VariableStatementList;

	public List<IExpression> _ExpressionList;
	public string _Value;
}

%%

start  		:  
			   {
					Ensure.NotNull(Logger).WriteLine("start -> epsilon");
			   }
		|
			   declaration_statement 
               { 
					Ensure.NotNull(Logger).WriteLine("start -> declaration_statement");
               }
		;

declaration_statement	: function
					  {
						  Ensure.NotNull(Logger).WriteLine("declaration_statement -> function");
					  }
|
					  type_declaration 
					  {
						  Ensure.NotNull(Logger).WriteLine("declaration_statement -> type_declaration");
					  }
|
					  function declaration_statement
					  {
						  Ensure.NotNull(Logger).WriteLine("declaration_statement -> function declaration_statement");
					  }
|	
					  type_declaration declaration_statement
					  {
						  Ensure.NotNull(Logger).WriteLine("declaration_statement -> type_declaration declaration_statement");
					  }	
		;

function	:	
				constraints PROCEDURE identifier_name LEFT_REGULAR_PARENTHESES RIGHT_REGULAR_PARENTHESES 
					declarations_block
				BEGIN 
					command_statement 
				END END_COMMAND
				{
					Ensure.NotNull(Logger).WriteLine("function -> PROCEDURE IDENTIFIER LEFT_REGULAR_PARENTHESES RIGHT_REGULAR_PARENTHESES BEGIN command_statement END END_COMMAND");

					var parameters = new List<IParameterDeclareStatement>();
					var commands = new List<IStatement>();

					_StatementFactory.CreateProcedure($3, parameters, $6.ToList(), commands);
				}
|
				constraints PROCEDURE identifier_name LEFT_REGULAR_PARENTHESES arguments RIGHT_REGULAR_PARENTHESES 
					declarations_block
				BEGIN 
					command_statement 
				END END_COMMAND
				{
					Ensure.NotNull(Logger).WriteLine("function -> PROCEDURE IDENTIFIER LEFT_REGULAR_PARENTHESES arguments RIGHT_REGULAR_PARENTHESES BEGIN command_statement END END_COMMAND");

					var parameters = new List<IParameterDeclareStatement>();
					var commands = new List<IStatement>();

					_StatementFactory.CreateProcedure($3, parameters, $7.ToList(), commands);
				}
|								  
				constraints operator_type OPERATOR STRING LEFT_REGULAR_PARENTHESES arguments RIGHT_REGULAR_PARENTHESES 
					PRECEDENCE NUMBER
					declarations_block
				BEGIN 
					command_statement 
				END END_COMMAND
				{
					Ensure.NotNull(Logger).WriteLine("function -> constraints operator_type OPERATOR STRING LEFT_REGULAR_PARENTHESES arguments RIGHT_REGULAR_PARENTHESES PRECEDENCE NUMBER");
				}
;

type_declaration:
				TYPE type_parameter END_COMMAND
				{
					Ensure.NotNull(Logger).WriteLine("type_declaration -> TYPE IDENTIFIER COLON type_parameter END_COMMAND");

					$$ = $2;
				}
;

type_name:		identifier_name
				{
					Ensure.NotNull(Logger).WriteLine("type_name -> identifier_name");		 
					$$ = $1;
				}
|
				identifier_name DOT type_name
				{
					Ensure.NotNull(Logger).WriteLine("type_name -> identifier_name DOT type_name");

					$$ = $1 + "." + $3;
				}
;

type_parameter:
				identifier_name COLON type_name
				{
					Ensure.NotNull(Logger).WriteLine("type_parameter -> identifier_name COLON identifier_name");

					$$ = _StatementFactory.CreateTypeDeclareStatement($1, $3);
				}
|
				identifier_name COLON LEFT_CURLY_PARENTHESES identifier_name COLON type_name LINEAR_COLON expression RIGHT_CURLY_PARENTHESES
				{	
					Ensure.NotNull(Logger).WriteLine("type_parameter -> identifier_name COLON LEFT_CURLY_PARENTHESES identifier_name COLON identifier_name LINEAR_COLON expression RIGHT_CURLY_PARENTHESES");

					$$ = _StatementFactory.CreateTypeDeclareStatement($1, $4, $6, $8);
				}
;


operator_type	:
					PREFIX
					{
						Ensure.NotNull(Logger).WriteLine("operator_type -> PREFIX");
					}
|
					INFIX
					{
						Ensure.NotNull(Logger).WriteLine("operator_type -> INFIX");
					}
|
					POSTFIX
					{
						Ensure.NotNull(Logger).WriteLine("operator_type -> POSTFIX");
					}
|
					ITERATIVE
					{
						Ensure.NotNull(Logger).WriteLine("operator_type -> ITERATIVE");
					}
;	

declarations_block: 
					declare_variable
					{
						Ensure.NotNull(Logger).WriteLine("declarations_block -> declare_variable");

						_StatementFactory.CreateVariableDeclarations($1.ToArray());

						$$ = $1;
					}
;
declare_variable:	
					{
						Ensure.NotNull(Logger).WriteLine("declarations_block -> epsilon");
						$$ = new List<IVariableStatement>();
					}
|
					declaration
					{
						Ensure.NotNull(Logger).WriteLine("declarations_block -> declaration");

						$$ = new[] { $1 };
					}
|
					declaration declare_variable
					{
						Ensure.NotNull(Logger).WriteLine("declarations_block -> declaration declarations_block");
						
						$$ = new[] { $1 }.Concat($2);
					}
;

declaration:		VAR identifier_name END_COMMAND
					{
						Ensure.NotNull(Logger).WriteLine("declarations_block -> VAR identifier_name END_COMMAND");
						$$ = _StatementFactory.DeclareVariable($2, "Infinity.Types.Undefined", null, false);
					}
|
					VAR identifier_name ASSIGNMENT expression END_COMMAND
					{
						Ensure.NotNull(Logger).WriteLine("declarations_block -> VAR identifier_name END_COMMAND");
						$$ = _StatementFactory.DeclareVariable($2, $4.ExpressionType.FullName, $4, false);
					}
|
					VAR identifier_name COLON type_name END_COMMAND
					{
						Ensure.NotNull(Logger).WriteLine("declarations_block -> VAR identifier_name COLON type_name END_COMMAND");
						$$ = _StatementFactory.DeclareVariable($2, $4, null, false);
					}
|					
					VAR identifier_name COLON type_name ASSIGNMENT expression END_COMMAND
					{
						Ensure.NotNull(Logger).WriteLine("declarations_block -> VAR identifier_name COLON type_name ASSIGNMENT expression END_COMMAND");
						$$ = _StatementFactory.DeclareVariable($2, $4, $6, false);
					};

arguments	:	/*identifier_name
				{
					Ensure.NotNull(Logger).WriteLine("arguments -> identifier_name");
				}
|
				identifier_name COLON type_parameter
				{
					Ensure.NotNull(Logger).WriteLine("arguments -> identifier_name COLON type_parameter");
				}
|
				identifier_name COMMA_SEPARATOR arguments
				{
					Ensure.NotNull(Logger).WriteLine("arguments -> identifier_name COMMA_SEPARATOR arguments");
				}
|
				identifier_name COLON type_parameter COMMA_SEPARATOR arguments
				{
					Ensure.NotNull(Logger).WriteLine("arguments -> identifier_name COLON type_parameter COMMA_SEPARATOR arguments");
				}*/
				identifier_name
				{
					Ensure.NotNull(Logger).WriteLine("arguments -> identifier_name");
				}
|			
				identifier_name COMMA_SEPARATOR arguments
				{
					Ensure.NotNull(Logger).WriteLine("arguments -> identifier_name COMMA_SEPARATOR arguments");
				}
|
				type_parameter
				{
					Ensure.NotNull(Logger).WriteLine("arguments -> type_parameter");
				}
|
				type_parameter COMMA_SEPARATOR arguments
				{
					Ensure.NotNull(Logger).WriteLine("argument -> type_parameter COMMA_SEPARATOR arguments");
				}
;

command_statement	: 
					{
						Ensure.NotNull(Logger).WriteLine("command_statement -> epsilon");

						$$ = _StatementFactory.CreateBlockStatement();
					}
|
					constraints SKIP END_COMMAND command_statement
					{	
						Ensure.NotNull(Logger).WriteLine("command_statement -> constraints END_COMMAND");

						$$ = _StatementFactory.CreateBlockStatement($4);
					}
|
					constraints block_statement END_COMMAND command_statement
					{
						Ensure.NotNull(Logger).WriteLine("command_statement -> constraints block_statement END_COMMAND command_statement");

						var statement = _StatementFactory.CreateConstraint($2, $1);
						var list = new[] { statement }.Concat($4.Commands);
						$$ = _StatementFactory.CreateBlockStatement(list.ToArray());
					}
|
					constraints if_statement END_COMMAND command_statement
					{
						Ensure.NotNull(Logger).WriteLine("command_statement -> constraints if_statement END_COMMAND command_statement");

						var statement = _StatementFactory.CreateConstraint($2, $1);
						var list = new[] { statement }.Concat($4.Commands);
						$$ = _StatementFactory.CreateBlockStatement(list.ToArray());
					}
|
					constraints while_statement END_COMMAND command_statement
					{
						Ensure.NotNull(Logger).WriteLine("command_statement -> constraints while_statement END_COMMAND command_statement");

						var statement = _StatementFactory.CreateConstraint($2, $1);
						var list = new[] { statement }.Concat($4.Commands);
						$$ = _StatementFactory.CreateBlockStatement(list.ToArray());
					}
|
					constraints for_statement END_COMMAND command_statement
					{
						Ensure.NotNull(Logger).WriteLine("for_statement -> constraints  for_statement END_COMMAND command_statement");

						var statement = _StatementFactory.CreateConstraint($2, $1);
						var list = new[] { statement }.Concat($4.Commands);
						$$ = _StatementFactory.CreateBlockStatement(list.ToArray());
					}
|
					constraints foreach_statement END_COMMAND command_statement
					{
						Ensure.NotNull(Logger).WriteLine("foreach_statement -> constraints foreach_statement END_COMMAND command_statement");

						var statement = _StatementFactory.CreateConstraint($2, $1);
						var list = new[] { statement }.Concat($4.Commands);
						$$ = _StatementFactory.CreateBlockStatement(list.ToArray());
					}
|
					constraints assignment END_COMMAND command_statement
					{
						Ensure.NotNull(Logger).WriteLine("command_statement -> constraints assignment END_COMMAND command_statement");

						var statement = _StatementFactory.CreateConstraint($2, $1);
						var list = new[] { statement }.Concat($4.Commands);
						$$ = _StatementFactory.CreateBlockStatement(list.ToArray());
					};

assignment	:	identifier_name ASSIGNMENT expression
				{
					Ensure.NotNull(Logger).WriteLine("assignment -> identifier_name ASSIGNMENT expression");

					$$ = _StatementFactory.CreateAssignment(_ExpressionFactory.CreateIdentifier($1), $3);
				}
|
				identifier_name ASSIGNMENT expression IF expression
				{
					Ensure.NotNull(Logger).WriteLine("assignment -> identifier_name ASSIGNMENT expression IF expression");

					var assignment = _StatementFactory.CreateBlockStatement(_StatementFactory.CreateAssignment(_ExpressionFactory.CreateIdentifier($1), $3));

					$$ = _StatementFactory.CreateIfStatement($5, assignment, null, null);
				}				
|
				identifier_name ASSIGNMENT expression WHILE expression
				{
					Ensure.NotNull(Logger).WriteLine("assignment -> identifier_name ASSIGNMENT expression WHILE expression");

					var assignment = _StatementFactory.CreateBlockStatement(_StatementFactory.CreateAssignment(_ExpressionFactory.CreateIdentifier($1), $3));

					$$ = _StatementFactory.CreateWhileStatement($5, assignment);
				}
;

block_statement :	BEGIN command_statement END
					{
						Ensure.NotNull(Logger).WriteLine("block_statement -> BEGIN command_statement END");

						StartStatement = $2;
						
						$$ = $2;
					}
|
					DECLARE declarations_block BEGIN command_statement END
					{
						Ensure.NotNull(Logger).WriteLine("block_statement -> DECLARE declarations_block BEGIN command_statement END");
						 
						StartStatement = $4;

						$$ = $4;
					}
;

if_statement	:	IF expression THEN command_statement else_if_statement END
					{
						Ensure.NotNull(Logger).WriteLine("if_statement -> IF expression THEN command_statement else_if_statement END");

						$$ = _StatementFactory.CreateIfStatement($2, $4, $5, null);
					}
|
					IF expression THEN command_statement else_if_statement ELSE command_statement END
					{
						Ensure.NotNull(Logger).WriteLine("if_statement -> IF expression THEN command_statement else_if_statement ELSE command_statement END");

						$$ = _StatementFactory.CreateIfStatement($2, $4, $5, $7);
					};

else_if_statement	:	
					{
						Ensure.NotNull(Logger).WriteLine("else_if_statement -> epsilon");

						$$ = new List<IIfStatement>();
					}
|
					ELSEIF expression THEN command_statement else_if_statement
					{
						Ensure.NotNull(Logger).WriteLine("else_if_statement -> ELSE IF expression THEN command_statement");

						var ifStatement = _StatementFactory.CreateIfStatement($2, $4, null, null);

						$$ = new[] { ifStatement }.Concat($5).ToList();
					};

while_statement	:	WHILE expression DO command_statement END
					{
						Ensure.NotNull(Logger).WriteLine("while_statement -> WHILE expression DO command_statement END");

						$$ = _StatementFactory.CreateWhileStatement($2, $4);
					};

for_statement:		FOR identifier_name ASSIGNMENT expression TO expression DO command_statement END
					{
						Ensure.NotNull(Logger).WriteLine("for_statement -> for IDENTIFIER ASSIGNMENT expression TO expression DO command_statement END");

						$$ = _StatementFactory.CreateForStatement(_ExpressionFactory.CreateIdentifier($2), $4, $6, null, $8);
					}
|
					FOR identifier_name ASSIGNMENT expression TO expression BY expression DO command_statement END
					{
						Ensure.NotNull(Logger).WriteLine("for IDENTIFIER ASSIGNMENT expression TO expression BY expression DO command_statement END");

						$$ = _StatementFactory.CreateForStatement(_ExpressionFactory.CreateIdentifier($2), $4, $6, $8, $10);
					};

foreach_statement:	FOREACH identifier_name IN expression DO command_statement END
					{
						Ensure.NotNull(Logger).WriteLine("foreach_statement -> foreach IDENTIFIER IN expression DO command_statement END");

						$$ = _StatementFactory.CreateForeachStatement(_ExpressionFactory.CreateIdentifier($2), $4, $6);
					};

constraints:
					{
						Ensure.NotNull(Logger).WriteLine("constraints -> epsilon");

						$$ = _StatementFactory.CreateConstraint(null, null, null);	
					}
|
					precondition
					{
						Ensure.NotNull(Logger).WriteLine("constraints -> precondition");

						$$ = _StatementFactory.CreateConstraint($1, null, null);
					}
|
					postcondition
					{
						Ensure.NotNull(Logger).WriteLine("constraints -> postcondition");

						$$ = _StatementFactory.CreateConstraint(null, $1, null);
					}
|
					precondition postcondition
					{
						Ensure.NotNull(Logger).WriteLine("constraints -> precondition postcondition");

						$$ = _StatementFactory.CreateConstraint($1, $2, null);
					}
|
					postcondition precondition
					{
						Ensure.NotNull(Logger).WriteLine("constraints -> postcondition precondition");

						$$ = _StatementFactory.CreateConstraint($2, $1, null);
					};

precondition:	
					LEFT_SQUARE_PARENTHESES PRECONDITION expression RIGHT_SQUARE_PARENTHESES
					{
						Ensure.NotNull(Logger).WriteLine("precondition -> LEFT_SQUARE_PARENTHESES 'Q' COLON expression RIGHT_SQUARE_PARENTHESES");

						$$ = $3;
					};

postcondition:	
					LEFT_SQUARE_PARENTHESES POSTCONDITION expression RIGHT_SQUARE_PARENTHESES
					{
						Ensure.NotNull(Logger).WriteLine("precondition -> LEFT_SQUARE_PARENTHESES 'R' COLON expression RIGHT_SQUARE_PARENTHESES");

						$$ = $3;
					};


expression:
					expression_base
					{
						Ensure.NotNull(Logger).WriteLine("expression -> expression_base");

						$$ = _ExpressionFactory.CreateExpression($1.Reverse<IExpression>().ToArray());
					}
/*|
					expression_base LEFT_REGULAR_PARENTHESES expression RIGHT_REGULAR_PARENTHESES expression_base
					{
						Ensure.NotNull(Logger).WriteLine("expression -> expression_base LEFT_REGULAR_PARENTHESES expression RIGHT_REGULAR_PARENTHESES expression_base");

						$$ = _ExpressionFactory.CreateExpression( $5.Concat(new[] { $3 }).Concat($1).ToArray() );
					}
|
					identifier_name LEFT_REGULAR_PARENTHESES arguments_list RIGHT_REGULAR_PARENTHESES expression_base
					{
						Ensure.NotNull(Logger).WriteLine("expression -> identifier_name LEFT_REGULAR_PARENTHESES arguments_list RIGHT_REGULAR_PARENTHESES expression_base");

						$$ = _ExpressionFactory.CreateExpression( $5.Concat( $3 ).Concat(new[] { _ExpressionFactory.CreateReference($1) }).ToArray() );
					}*/
;

expression_base	:	
					{
						Ensure.NotNull(Logger).WriteLine("expression_base -> epsilon");

						$$ = new List<IExpression>();
					}
|
					element expression_base
					{
						Ensure.NotNull(Logger).WriteLine("expression_base -> element expression_base");

						$2.Add($1);

						$$ = $2;
					}
|
					LEFT_REGULAR_PARENTHESES RIGHT_REGULAR_PARENTHESES expression_base
					{
						Ensure.NotNull(Logger).WriteLine("expression_base -> LEFT_REGULAR_PARENTHESES RIGHT_REGULAR_PARENTHESES");

						$3.Add(_ExpressionFactory.CreateTupleConstant());

						$$ = $3;
					}
|
					LEFT_REGULAR_PARENTHESES arguments_list RIGHT_REGULAR_PARENTHESES expression_base
					{
						Ensure.NotNull(Logger).WriteLine("expression_base -> LEFT_REGULAR_PARENTHESES arguments_list RIGHT_REGULAR_PARENTHESES");

						if ($2.Count() == 1)
						{
							$4.Add($2.First());
						}
						else
						{
							$4.Add(_ExpressionFactory.CreateTupleConstant($2.ToArray()));
						}

						$$ = $4;
					}
;

element		:
				constant
				{
					Ensure.NotNull(Logger).WriteLine("element -> constant");

					$$ = $1;
				}
|
				identifier_name
				{
					Ensure.NotNull(Logger).WriteLine("element -> identifier_name: {0}", $1);

					//$$ = _ExpressionFactory.CreateIdentifier($1);

					$$ = _ExpressionFactory.CreateReference($1);
				}
|
				symbol_name
				{
					Ensure.NotNull(Logger).WriteLine("element -> symbol_name: {0}", $1);

					//$$ = _ExpressionFactory.CreateIdentifier($1);

					$$ = _ExpressionFactory.CreateReference($1);
				}
|
				COLON
				{
					Ensure.NotNull(Logger).WriteLine("element -> COLON");

					//$$ = _ExpressionFactory.CreateReference(":");

					$$ = _ExpressionFactory.CreateSymbol(":");
				}
|
				IN
				{
					Ensure.NotNull(Logger).WriteLine("element -> IN");

					$$ = _ExpressionFactory.CreateSymbol("in");
				}
|
				DOT
				{
					Ensure.NotNull(Logger).WriteLine("element -> DOT");

					$$ = _ExpressionFactory.CreateSymbol(".");
				}
|
				LEFT_SQUARE_PARENTHESES arguments_list RIGHT_SQUARE_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("range_constant -> LEFT_SQUARE_PARENTHESES expression DOTS expression RIGHT_SQUARE_PARENTHESES");

					$$ = _ExpressionFactory.CreateIndexer($2.ToArray());
				}
/*
|
				COMMA_SEPARATOR
				{
					Ensure.NotNull(Logger).WriteLine("element -> COMMA_SEPARATOR");

					$$ = _ExpressionFactory.CreateSymbol(",");
				}
|
				LEFT_REGULAR_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("element -> LEFT_REGULAR_PARENTHESES");

					$$ = _ExpressionFactory.CreateSymbol("(");
				}
|
				RIGHT_REGULAR_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("element -> RIGHT_REGULAR_PARENTHESES");

					$$ = _ExpressionFactory.CreateSymbol(")");
				}
				LEFT_REGULAR_PARENTHESES arguments_list RIGHT_REGULAR_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("element -> LEFT_REGULAR_PARENTHESES arguments_list RIGHT_REGULAR_PARENTHESES");

					$$ = _ExpressionFactory.CreateSymbol("(");
				}
*/
;

identifier_name	:
				IDENTIFIER
				{
					Ensure.NotNull(Logger).WriteLine("identifier_name -> IDENTIFIER: {0}", yytext);

					$$ = yytext;
				}
;
symbol_name	:
				SYMBOL
				{
					Ensure.NotNull(Logger).WriteLine("symbol_name -> SYMBOL: {0}", yytext);

					$$ = yytext;
				}
;

constant	:	STRING
				{
					Ensure.NotNull(Logger).WriteLine("constant -> STRING '{0}'", yytext);

					$$ = _ExpressionFactory.CreateStringConstant(yytext);
				}
|
				BOOLEAN
				{
					Ensure.NotNull(Logger).WriteLine("constant -> BOOLEAN {0}", yytext);

					$$ = _ExpressionFactory.CreateBooleanConstant(Convert.ToBoolean(yytext));
				}
|
				NUMBER
				{
					Ensure.NotNull(Logger).WriteLine("constant -> NUMBER {0}", yytext);

					$$ = _ExpressionFactory.CreateNumberConstant(Convert.ToDouble(yytext));
				}
|
				set_constant
				{
					Ensure.NotNull(Logger).WriteLine("constant -> set_constant");

					$$ = $1;
				}
|
				range_constant
				{
					Ensure.NotNull(Logger).WriteLine("constant -> range_constant");

					$$ = $1;
				}
;

range_constant:
				LEFT_SQUARE_PARENTHESES expression DOTS expression RIGHT_SQUARE_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("range_constant -> LEFT_SQUARE_PARENTHESES expression DOTS expression RIGHT_SQUARE_PARENTHESES");

					$$ = _ExpressionFactory.CreateRangeConstant($2, $4, null);
				}
;

set_identifier: identifier_name COLON expression
				{
					$$ = _ExpressionFactory.CreateLazySetIdentifier($1, $3);
				}
;

set_identifier_list : set_identifier
					  {	
						$$ = new List<IVariableStatement> { $1 }.ToArray();
					  }
|	
					  set_identifier COMMA_SEPARATOR set_identifier_list
					  {
						$$ = $3.Concat(new[] { $1 }).ToArray();
					  }
;			

set_constant:
				LEFT_CURLY_PARENTHESES RIGHT_CURLY_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("set_constant -> LEFT_CURLY_PARENTHESIS RIGHT_CURLY_PARENTHESIS");

					$$ = _ExpressionFactory.CreateSetConstant();
				}
|
				LEFT_CURLY_PARENTHESES arguments_list RIGHT_CURLY_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("set_constant -> LEFT_CURLY_PARENTHESIS arguments_list RIGHT_CURLY_PARENTHESIS");

					$$ = _ExpressionFactory.CreateSetConstant($2.ToArray());
				}
|
				LEFT_CURLY_PARENTHESES set_identifier_list LINEAR_COLON expression RIGHT_CURLY_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("set_constant -> LEFT_CURLY_PARENTHESES set_identifier LINEAR_COLON expression RIGHT_CURLY_PARENTHESES");
					
					$$ = _ExpressionFactory.CreateLazySetConstant($2.ToArray(), _ExpressionFactory.CreateIdentifier($2.First().Name), $4);
				}
|
				LEFT_CURLY_PARENTHESES expression WHERE set_identifier_list LINEAR_COLON expression RIGHT_CURLY_PARENTHESES
				{
					Ensure.NotNull(Logger).WriteLine("set_constant -> LEFT_CURLY_PARENTHESES set_identifier LINEAR_COLON expression RIGHT_CURLY_PARENTHESES");

					$$ = _ExpressionFactory.CreateLazySetConstant($4.ToArray(), $2, $6);

					//$$ = _ExpressionFactory.CreateLazySetConstant($2, $4);
				}
;

arguments_list:
				expression
				{
					Ensure.NotNull(Logger).WriteLine("arguments_list -> expression");

					$$ = new List<IExpression>() { $1 };
				}
|
				expression COMMA_SEPARATOR arguments_list
				{
					Ensure.NotNull(Logger).WriteLine("arguments_list -> expression COMMA_SEPARATOR arguments_list");

					$3.Add($1);

					$$ = $3;
				}
;
%%

	public SyntaxParser(LexicalParser parser, IStatementFactory statementFactory, IExpressionFactory expressionFactory) : base(parser) 
	{
		_StatementFactory = Ensure.NotNull(statementFactory);
		_ExpressionFactory = Ensure.NotNull(expressionFactory);
		
		_StatementFactory.ExpressionFactory = _ExpressionFactory;
		_ExpressionFactory.StatementFactory = _StatementFactory;

		Logger = _StatementFactory.Logger;
	}

	public SyntaxParser(LexicalParser parser, IStatementFactory statementFactory) : base(parser) 
	{
		_StatementFactory = Ensure.NotNull(statementFactory);
		_ExpressionFactory = Ensure.NotNull(statementFactory.ExpressionFactory);

		Logger = _StatementFactory.Logger;
	}